#ifndef _MODBUS_SERIAL_PORT_H_
#define _MODBUS_SERIAL_PORT_H_

#include "serial_port.h"

class ModbusBase {
 public:
  // 功能码定义
  enum FunctionCode {
    ReadCoils = 0x01,           // 读线圈
    ReadDiscreteInputs = 0x02,  // 读离散输入
    ReadHoldingRegs = 0x03,     // 读保持寄存器（主站常用）
    ReadInputRegs = 0x04,       // 读输入寄存器
    WriteSingleCoil = 0x05,     // 写单个线圈
    WriteSingleRegs = 0x06,     // 写单个寄存器
    WriteMultipleCoils = 0x0F,  // 写多个线圈
    WriteMultipleRegs = 0x10    // 写多个寄存器
  };

  ModbusBase(SerialPort& serial, int timeout_ms = 3000,
             size_t max_buffer_size = 128, uint8_t slave_addr = 0x01);

  virtual ~ModbusBase();

  // 设置超时时间
  void SetTimeout(int timeoutMs) { m_timeout_ms_ = timeoutMs; }

  void SetSlaveAddress(const uint8_t addr) { m_slave_addr_ = addr; }
  // 读取完整帧（从串口接收数据并提取）
  std::vector<uint8_t> ReadCompleteFrame();

  // 从缓冲区提取完整帧
  std::vector<uint8_t> ExtractCompleteFrame();

  // 判断数据帧校验是否成功，并且返回一条数据帧的总长度
  virtual size_t CheckCompleteFrame(const std::vector<uint8_t>& buf) = 0;

  // 开始运行
  virtual void Start() = 0;

 protected:
  SerialPort& m_serial_;  // 串口对象引用

  std::vector<uint8_t> m_rx_buffer_;       // 接收缓冲区
  std::vector<uint8_t> m_pending_buffer_;  // 存放已经获取到的数据帧

  int m_timeout_ms_;          // 超时时间(ms)
  size_t m_max_buffer_size_;  // 最大缓冲区大小
  uint8_t m_slave_addr_;      // 从站地址
};

// 主站
class ModbusMaster : public ModbusBase {
 public:
  // 主站构造函数
  ModbusMaster(SerialPort& serial, int timeout_ms = 3000,
               size_t max_buffer_size = 128);
  // 发送请求，并处理响应
  void Start() override;

 private:
  // 生成请求帧
  std::vector<uint8_t> GenerateMasterRequest(uint8_t slave_addr,
                                             uint8_t func_code,
                                             uint16_t start_addr,
                                             uint16_t count);
  // 解析响应帧
  bool ParseMasterResponse(const std::vector<uint8_t>& response,
                           uint8_t func_code);
  size_t CheckCompleteFrame(const std::vector<uint8_t>& bufffer) override;
};

// 从站
class ModbusSlave : public ModbusBase {
 public:
  // 从站构造函数
  ModbusSlave(SerialPort& serial, int timeout_ms = 3000,
              size_t max_buffer_size = 128);
  // 开始接收请求,并发送响应
  void Start() override;

 private:
  // 解析请求帧
  bool ParseRequest(const std::vector<uint8_t>& request, uint8_t& device_addr,
                    uint8_t& func_code, uint16_t& start_addr, uint16_t& count);
  // 校验请求数据的完整性与准确性，并返回数据包长度
  size_t CheckCompleteFrame(const std::vector<uint8_t>& buffer) override;
  // 生成响应帧
  std::vector<uint8_t> GenerateSlaveResponse(
      const std::vector<uint8_t>& request);
  // 解析请求帧
  bool ParseSlaveRequest(const std::vector<uint8_t>& request,
                         uint8_t& device_addr, uint8_t& func_code,
                         uint16_t& start_addr, uint16_t& count);
};

#endif